package com.bite.f.service.user.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bite.common.core.constants.CacheConstants;
import com.bite.common.core.constants.Constants;
import com.bite.common.core.constants.HttpConstants;
import com.bite.common.core.enums.ResultCode;
import com.bite.common.core.enums.UserIdentity;
import com.bite.common.core.enums.UserStatus;
import com.bite.common.redis.service.RedisService;
import com.bite.common.security.exception.ServiceException;
import com.bite.common.security.service.TokenService;
import com.bite.f.domain.user.User;
import com.bite.f.domain.user.dto.UserDTO;
import com.bite.f.mapper.user.UserMapper;
import com.bite.f.service.user.IUserService;
import com.github.pagehelper.util.StringUtil;
import common.bite.common.message.service.AliSmsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class UserServiceImpl implements IUserService {
    @Value("${sms.code-expiration:5}")
    private Long phoneCodeExpiration;
    @Value("${sms.send-limit:3}")
    private Long sendLimit;
//    @Value("${jwt.secret:1}")
//    private String secret;
    @Value("${sms.is-send:false}")
    private boolean isSend;//开关打开：true
    @Value("${file.oss.downLoadUrl}")
    private String downLoadUrl;
    @Autowired
    private AliSmsService aliSmsService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TokenService tokenService;

    @Override
    public boolean sendCode(UserDTO userDTO) {
        String phone = userDTO.getPhone();
        if(!checkPhone(phone)) {
            throw new ServiceException(ResultCode.FAILED_USER_PHONE);
        }
        //判断是否在一分钟内重复获取验证码
        String phoneCodeKey = getPhoneCodeKey(phone);
        Long expire = redisService.getExpire(phoneCodeKey,TimeUnit.SECONDS);
        if(expire != null && (expire - 240) > 0){
            throw new ServiceException(ResultCode.FAILED_FREQUENT);
        }
        //每天限制发送50次
        String codeTimeKey = getCodeTimeKey(phone);
        Long sendTimes = redisService.getCacheObject(codeTimeKey,Long.class);
        if(sendTimes != null && sendTimes >= sendLimit){
            throw new ServiceException(ResultCode.FAILED_TIME_LIMIT);
        }
        redisService.increment(codeTimeKey);


        //设置时间
        if (sendTimes == null) { // 说明是当天第一次发起获取验证码的请求
            long seconds = ChronoUnit.SECONDS.between(
                    LocalDateTime.now(),
                    LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0).plusDays(1)
            );
            redisService.expire(codeTimeKey,seconds,TimeUnit.SECONDS);
        }

        //生辰随机验证码
        String code = isSend ? RandomUtil.randomNumbers(6) : Constants.DEFAULT_CODE;
        redisService.setCacheObject(phoneCodeKey, code, phoneCodeExpiration, TimeUnit.MINUTES);
        //发送验证码
        if(isSend) {
            return aliSmsService.sendMobileCode(phone, code);
        }
        return true;
    }

    @Override
    public String login(String phone ,String code) {
        validateCode(phone, code);
        // 查询用户
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, phone));
        if(user == null){
            user = new User();
            user.setPhone(phone);
            //user.setStatus(UserStatus.Normal.getStatus());
            userMapper.insert(user);
        }
        return null;
        //return tokenService.createToken(user.getUserId(), secret, UserIdentity.ORDINARY.getValue(), user.getNickName());
    }

    @Override
    public boolean logout(String token) {
        //解析token，将redis中的相关数据删除
        token = d(token);
        return tokenService.deleteLoginUser(token,null);
    }

    private String d(String token){
        if (StrUtil.isNotEmpty(token) &&
                token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        return token;
    }

    /**
     * 校验验证码
     */
    private void validateCode(String phone, String code) {
        String phoneCodeKey = getPhoneCodeKey(phone);
        String cacheCode = redisService.getCacheObject(phoneCodeKey, String.class);

        // 验证码为空
        if (StringUtil.isEmpty(cacheCode)) {
            throw new ServiceException(ResultCode.FAILED_INVALID_CODE);
        }

        // 验证码不匹配
        if (!cacheCode.equals(code)) {
            throw new ServiceException(ResultCode.FAILED_ERROR_CODE);
        }
        // 验证码比对成功，删除 Redis 中的验证码
        redisService.deleteObject(phoneCodeKey);
    }

    private String getCodeTimeKey(String phone) {
        return CacheConstants.CODE_TIME_KEY + phone;
    }

    private String getPhoneCodeKey(String phone) {
        return CacheConstants.PHONE_CODE_KEY + phone;
    }


    public static boolean checkPhone(String phone) {
        Pattern regex = Pattern.compile("^1[2|3|4|5|6|7|8|9][0-9]{9}$");
        Matcher m = regex.matcher(phone);
        return m.matches();
    }
}
































